#ifndef AZFIELD_H
#define AZFIELD_H

#include <QString>
#include <QVariant>
#include <QVector>
#include <QHash>
#include <QXmlStreamWriter>

#include "Az.h"

class AzFieldList;
class AzAbstractDataSource;
class AzRootRecord;
class AzRecordValues;


class AzFieldException: public AzException {
public:
    enum Error {
        CannotChangeFieldError,
        InvalidFieldTypeError
    };
    AzFieldException(Error err);
private:
    static QString codeToStr(Error);
    Error mErrCode;
};

class AZLIB_EXPORT AzField: public QObject {
Q_OBJECT
Q_ENUMS(FieldKind)
friend class AzFieldList;
public:
    AzField();
	AzField(const AzField&);
    ~AzField();
	
	enum FieldKind {
        DataFieldKind,
        CalcFieldKind
	};

	QVariant::Type type() const				{ return mType; }
	QString typeName() const				{ return QVariant::typeToName(mType); }
	void setType(const QString& name)		{ mType = QVariant::nameToType(name.toLatin1().data()); }
    void setType(QVariant::Type type)		{ mType = type; }
    void setName(const QString& name)       { mName = name; }
    inline QString name() const				{ return mName; }
	QString displayName() const				{ return mDisplayName; }
	int lenght() const						{ return mLenght; }
	void setLenght(int val)					{ mLenght = val; }
	void setDisplayName(const QString& val) { mDisplayName = val; }
	FieldKind fieldKind() const				{ return mFieldKind; }
	void setFieldKind(FieldKind kind)		{ mFieldKind = kind; }

    Q_PROPERTY(QString name READ name WRITE setName)
	Q_PROPERTY(QString type READ typeName WRITE setType)
	Q_PROPERTY(int lenght READ lenght WRITE setLenght)
	Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName)
    Q_PROPERTY(FieldKind fieldKind READ fieldKind WRITE setFieldKind)


    AzField& operator = (const AzField& src);

protected:
    void writeXml(QXmlStreamWriter&) const;
    void readData(const QXmlStreamAttributes&);
private:
    void copy(const AzField&);
	QString mName;
	QVariant::Type mType;
	QString mDisplayName;
	int mLenght;
	FieldKind mFieldKind;
};

class AZLIB_EXPORT AzFieldList: public QObject {
Q_OBJECT
Q_ENUMS (FieldChangedSignalType)
    friend class AzField;
    friend class AzRootRecord;
public:
    enum FieldChangedSignalType {
        OnInserted      =       0x0,
        OnDeleted       =       0x1,
        OnModified      =       0x2,
        OnReset         =       0x3
    };

    explicit AzFieldList(QObject *parent = 0);
    AzFieldList(const AzFieldList &);
    virtual ~AzFieldList();

    inline int size() const								{ return mFields.size(); }

	int indexOf(const QString&);
	bool isNameExist(const QString&);

	void append(const QString& name, const AzField&);
    void clear();

    AzRecordValues  fieldsType() const;

    const AzField& operator[] (int i) const				{ return mFields[i]; }
    const AzField& field(int i) const					{ return mFields[i]; }
    inline QVariant::Type type(int i) const             { return mFields[i].type(); }

    AzFieldList& operator = (const AzFieldList&);

signals:
    void fieldChanged(AzFieldList::FieldChangedSignalType,int);
protected:

private:
    explicit AzFieldList(const AzRootRecord*);
    void copy(const AzFieldList&);
    void checkIsCanChange() const;
    QVector<AzField> mFields;
    const AzRootRecord *mRootRec;
};


#endif // AZFIELD_H
